import 'dart:async';
import 'dart:math';

import 'package:dio/dio.dart';
import 'package:flutter_base_app/config/i18n/i18n.dart';
import 'package:flutter_base_app/utils/http/http_extends.dart';
import 'package:flutter_base_app/utils/http/http_manager.dart';
import 'package:flutter_common_utils/common_utils_export.dart';
import 'package:flutter_base_app/utils/other/log_config.dart';

import '../../config/i18n/i18n_key.dart';
import '../user/user_help.dart';
import 'http_code.dart';

///网络请求 日志拦截器
class LoggingInterceptor extends Interceptor {
  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    options.startTime = currentTimeMillis;
    super.onRequest(options, handler);
  }

  @override
  Future onResponse(Response response, ResponseInterceptorHandler handler) async {
    try {
      if (LogConfig.httpIsLog) {
        final options = response.requestOptions;
        final logMap = {
          "request": {
            "uri": options.uri,
            "method": options.method,
            "headers": options.headers,
            "data": options.data,
          },
          "response": {
            "code": response.statusCode,
            // "headers": response.headers.map,
            "data": response.data,
          }
        };
        LogUtils.d(logMap);
      }
      // LogUtils.d("********************************************Http请求开始********************************************\n"
      //     "*********************************************Request********************************************\n"
      //     "${options.requestStr()}\n"
      //     "*********************************************Response*******************************************\n"
      //     "${response.responseStr()}\n"
      //     "time : ${(currentTimeMillis - options.startTime)} \n"
      //     "********************************************Http请求结束********************************************");
    } catch (e) {
      return response;
    }
    super.onResponse(response, handler);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    // LogUtils.d("********************************************Http请求开始********************************************\n"
    //     "*********************************************Request********************************************\n"
    //     "${err.requestOptions.requestStr()}\n\n"
    //     "*********************************************Response Error*******************************************\n"
    //     "${err.response?.responseStr()}\n\n"
    //     "${err.error}\n\n"
    //     "${err.message}\n\n"
    //     "********************************************Http请求结束********************************************\n");
    if (LogConfig.httpIsLog) {
      final logMap = {
        "request": {
          "uri": err.requestOptions.uri,
          "method": err.requestOptions.method,
          "headers": err.requestOptions.headers,
          "data": err.requestOptions.data,
        },
        "response": {
          'code': err.response?.statusCode,
          // "headers": err.headers.map,
          "error": err.error,
          "message": err.message,
          "data": err.response?.data,
        }
      };
      LogUtils.d(logMap);
    }
    super.onError(err, handler);
  }
}

/// 刷新token拦截器
class RefreshTokenInterceptor extends Interceptor {
  Completer<void>? _refreshCompleter;

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) async {
    final contentType = response.headers.value("Content-Type")?.orEmpty() ?? '';
    if (contentType.contains("json") && response.data['code'] == HttpCodeApp.ACCESS_TOKEN_EXPIRE) {
      final requestOptions = response.requestOptions;
      final key = Random().nextInt(9999999);
      LogUtils.e("token 已过期 ：${_refreshCompleter?.isCompleted},,key=$key");
      // 防止重复刷新
      if (_refreshCompleter?.isCompleted == false) {
        // 将请求加入等待队列
        return _waitRefreshThenRetry(response, handler, key);
      }
      // 首次，开始刷新流程
      _refreshCompleter = Completer();
      // Token 过期，尝试刷新 Token
      try {
        final newToken = await _refreshToken();
        LogUtils.e("token 刷新返回 ：key=$key，newToken=$newToken");
        if (newToken != null) {
          HttpManager.getInstance().setCommonParams();
          // 重试请求
          LogUtils.e("token 刷新完成 ：key=$key");
          final responseNew = await _retryRequest(requestOptions);
          LogUtils.e("token 刷新完成,再次请求结果 ：key=$key,${responseNew.data}");
          handler.next(responseNew);
          return;
        } else {
          UserHelp.cleanData();
          //构建一个错误码为10401的错误返回
          response.data = {"code": HttpCodeApp.AUTH_ERROR, "message": I18nKey.no_login.trx};
          handler.next(response);
        }
      } catch (e) {
        //构建一个错误码为10401的错误返回
        response.data = {"code": HttpCodeApp.AUTH_ERROR, "message": I18nKey.no_login.trx};
        handler.next(response);
      } finally {
        //完成
        _refreshCompleter?.complete();
        _refreshCompleter = null;
      }
    } else {
      super.onResponse(response, handler);
    }
  }

  Future<Response> _retryRequest(RequestOptions options) {
    // 更新请求头中的 Token
    options.headers['accessToken'] = UserHelp.userData?.token;
    return HttpManager.dio.request(
      options.path,
      options: Options(
        method: options.method,
        headers: options.headers,
      ),
      data: options.data,
      queryParameters: options.queryParameters,
    );
  }

  Future<String?> _refreshToken() async {
    // 调用刷新 Token 的接口
    if ((UserHelp.userData?.refreshToken).isNullOrEmpty()) return null;
    try {
      final response = await HttpManager.dio.post(HttpManager.createUrl(path: '/user/login/refresh-token'), data: {
        'refreshToken': UserHelp.userData?.refreshToken ?? "",
      });
      if (response.statusCode == 200) {
        final newToken = response.data['data']['accessToken'];
        final newRefreshToken = response.data['data']['refreshToken'];
        UserHelp.userData?.refreshToken = newRefreshToken;
        UserHelp.userData?.token = newToken;
        UserHelp.userData?.save();
        // 保存新的 Token
        // _saveToken(newToken);
        return newToken;
      }
    } catch (e) {
      return null;
    }
    return null;
  }

  Future<void> _waitRefreshThenRetry(Response response, ResponseInterceptorHandler handler, int key) async {
    try {
      await _refreshCompleter?.future;
      //如果没有登录
      if (!UserHelp.isLogin) {
        //构建一个错误码为10401的错误返回
        response.data = {"code": HttpCodeApp.AUTH_ERROR, "message": I18nKey.no_login.trx};
        handler.next(response);
      }
      LogUtils.e("token 等待返回结果 ：key=$key");
      final retryResponse = await _retryRequest(response.requestOptions);
      LogUtils.e("token 再次调用结果 ：key=$key，${retryResponse.data}");
      handler.resolve(retryResponse);
    } catch (e) {
      response.data = {"code": HttpCodeApp.AUTH_ERROR, "message": I18nKey.no_login.trx};
      handler.next(response);
    }
  }
}
